package my.design.command;

/**
 * @author zp
 * @version 1.0
 * @description: 遥控器类
 * 命令设计模式
 * 1、Command（抽象命令类）：抽象命令类一般是一个抽象类或接口，在其中声明了用于执行请求的execute()等方法，
 * 通过这些方法可以调用请求接收者的相关操作。
 * 2、LightOffCommand（具体命令类）：具体命令类是抽象命令类的子类，实现了在抽象命令类中声明的方法，
 * 它对应具体的接收者对象，将接收者对象的动作绑定其中。在实现execute()方法时，将调用接收者对象的相关操作(Action)。
 * 3、RemoteController（调用者）：调用者即请求发送者，它通过命令对象来执行请求。
 * 一个调用者并不需要在设计时确定其接收者，因此它只与抽象命令类之间存在关联关系。
 * 在程序运行时可以将一个具体命令对象注入其中，再调用具体命令对象的execute()方法，从而实现间接调用请求接收者的相关操作。
 * 4、LightReceiver（接收者）：接收者执行与请求相关的操作，它具体实现对请求的业务处理。
 *
 * 可以把命令模式抽象成三个组织者 （自己的语言理解）
 * 被调用者 可以定义接口或者抽象类 实现方法 具体的被命令操作的对象 LightReceiver
 * 命令类 也可以是抽象类或者接口 具体实现类需要聚合被调用者 实现命令驱动事物执行操作 LightOffCommand
 * 组装类 聚合具体的命令实现不同的操作 可以有不同的组合和实现 RemoteController
 * 测试对象 -》调用组装类 -》组装类聚合命令对象-》命令对象聚合被调用者
 * RemoteController -》 LightOffCommand -》LightReceiver
 * 实现具体实现和被调用者的解耦关系
 * 使用一个字中间对象 削弱其的影响
 *
 * 在JdbcTemplate当中也使用到了命令模式
 * 每一个增删改查 对应不同的命令接口（UpdateStatementCallback、QueryStatementCallback、BatchUpdateStatementCallback、ExecuteStatementCallback实现类）
 * 对应
 * update() 方法
 * query() 方法
 * batch() 方法
 * execute() 方法
 * 每个方法都有一个实现对应接口的内部类
 * 都会执行接口的方法
 * 类似于命令模式
 * @date 2022/10/20 18:59
 */
public class RemoteController {
    //开关按钮的命令数组
    Command[] onCommands;
    Command[] offCommands;
    //执行撤销按钮操作
    Command undoCommand;

    //构造器，完成对按钮的初始化
    public RemoteController() {
        onCommands = new Command[5];
        offCommands = new Command[5];
        for (int i = 0; i < 5; i++) {
            onCommands[i] = new NoCommand();
            offCommands[i] = new NoCommand();
        }
    }

    //给我们的按钮设置你需要的命令即可
    public void setCommand(int no, Command onCommand, Command offCommand) {
        onCommands[no] = onCommand;
        offCommands[no] = offCommand;
    }

    //按下开按钮
    public void onButtonWasPushed(int no) {
        onCommands[no].execute();
        //记录这次操作，用于撤销
        undoCommand = onCommands[no];
    }

    public void offButtonWasPushed(int no) {
        offCommands[no].execute();
        undoCommand = offCommands[no];
    }

    //撤销
    public void undoButtonWasPushed() {
        undoCommand.undo();
    }
}
